package com.mrogrape.messager;

import java.io.IOException;
import java.io.Serializable;

/**
 * 标记一个消息容器对象，用来对消息进行储存。
 * 
 * <p>
 * 此消息中包含一组putXXX方法和getXXX方法，用来包装数据。一般来说，通过put方法放入数据
 * 和通过get方法获取数据时类型应该是相同的，但是，并不强制要求这么做。如果你调用Get方法
 * 获取某个类型的值，那么在键存在的情况下getter会尝试将值转化为当前获取的类型。例如：
 * 你可以放入一个整形的数据却通过long型数据获取方法将其取出。
 * 
 * <p>
 * 注意：类型的转化是不被检查的，这意味着有可能在转化的过程中发生精度丢失等情况。所以，
 * 除非你确认需要使用这样的特性，否则不要使用不同的setter和getter来操作同一个值。
 * 
 * @author Ice Spring
 * 
 */
public interface MessageBundle extends Serializable{

	/**
	 * 获取此消息的ID，此ID应最大限度的保证唯一性和不可变性。
	 * 
	 * @return 此消息的ID。
	 */
	public long getId();
	
	/**
	 * 将一个byte类型的数据添加至此MessageContainer中。
	 * 
	 * @param key 键。
	 * @param value 值。
	 */
	public void putByte(String key, byte value);
	
	/**
	 * 将一个int类型的数据添加至此MessageContainer中。
	 * 
	 * @param key 键。
	 * @param value 值。
	 */
	public void putInt(String key, int value);
	
	/**
	 * 将一个short类型的数据添加至此MessageContainer中。
	 * 
	 * @param key 键。
	 * @param value 值。
	 */
	public void putShort(String key, short value);
	
	/**
	 * 将一个long类型的数据添加至此MessageContainer中。
	 * 
	 * @param key 键。
	 * @param value 值。
	 */
	public void putLong(String key, long value);
	
	/**
	 * 将一个char类型的数据添加至此MessageContainer中。
	 * 
	 * @param key 键。
	 * @param value 值。
	 */
	public void putChar(String key, char value);
	
	/**
	 * 将一个boolean类型的数据添加至此MessageContainer中。
	 * 
	 * @param key 键。
	 * @param value 值。
	 */
	public void putBoolean(String key, boolean value);
	
	/**
	 * 将一个double类型的数据添加至此MessageContainer中。
	 * 
	 * @param key 键。
	 * @param value 值。
	 */
	public void putDouble(String key, double value);
	
	/**
	 * 将一个float类型的数据添加至此MessageContainer中。
	 * 
	 * @param key 键。
	 * @param value 值。
	 */
	public void putFloat(String key, float value);
	
	/**
	 * 将一个String类型的数据添加至此MessageContainer中。
	 * 
	 * @param key 键。
	 * @param value 值。
	 */
	public void putString(String key, String value);
	
	/**
	 * 从此MessageContainer对象中取出一个byte类型的值。
	 * 
	 * @param key 键
	 * @return 取出的值，如果不存在则为null。
	 */
	public Byte getByte(String key);
	
	/**
	 * 从此MessageContainer对象中取出一个Integer类型的值。
	 * 
	 * @param key 键
	 * @return 取出的值，如果不存在则为null。
	 */
	public Integer getInt(String key);
	
	/**
	 * 从此MessageContainer对象中取出一个Short类型的值。
	 * 
	 * @param key 键
	 * @return 取出的值，如果不存在则为null。
	 */
	public Short getShort(String key);
	
	/**
	 * 从此MessageContainer对象中取出一个Long类型的值。
	 * 
	 * @param key 键
	 * @return 取出的值，如果不存在则为null。
	 */
	public Long getLong(String key);
	
	/**
	 * 从此MessageContainer对象中取出一个Character类型的值。
	 * 
	 * @param key 键
	 * @return 取出的值，如果不存在则为null。
	 */
	public Character getChar(String key);
	
	/**
	 * 从此MessageContainer对象中取出一个Boolean类型的值。
	 * 
	 * @param key 键
	 * @return 取出的值，如果不存在则为null。
	 */
	public Boolean getBoolean(String key);
	
	/**
	 * 从此MessageContainer对象中取出一个Double类型的值。
	 * 
	 * @param key 键
	 * @return 取出的值，如果不存在则为null。
	 */
	public Double getDouble(String key);
	
	/**
	 * 从此MessageContainer对象中取出一个Float类型的值。
	 * 
	 * @param key 键
	 * @return 取出的值，如果不存在则为null。
	 */
	public Float getFloat(String key);
	
	/**
	 * 从此MessageContainer对象中取出一个String类型的值。
	 * 
	 * @param key 键
	 * @return 取出的值，如果不存在则为null。
	 */
	public String getString(String key);
	
	/**
	 * 对此Message进行编码。
	 * 
	 * <p>
	 * 此方法的实现者应保证通过此方法编码后的数据再经过{@link #decode(byte[])}
	 * 解码后调用equals方法应返回true。
	 * 
	 * @return 编码后得到的数据
	 */
	public byte[] encode() throws IOException;
	
	/**
	 * 清空当前Message中所保存的全部数据，然后解码给定byte[]数组中的数据并填充。
	 * 
	 * <p>
	 * 参数为通过{@link #encode()}编码的数据。此方法的实现者应保证通过此方法解码后，
	 * 当前对象和源对象调用equals方法返回true。
	 * 
	 * @param key 键
	 * @return 取出的值，如果不存在则为null。
	 */
	public void decode(byte[] data) throws IOException;
	
	/**
	 * 获取全部的键。
	 * 
	 * @return 储存着全部键的数组
	 */
	public String[] getKeys();
}
